package wint.mvc.pipeline.valves;

import wint.core.config.Configuration;
import wint.core.config.Constants;
import wint.lang.exceptions.FlowDataException;
import wint.lang.magic.MagicList;
import wint.lang.utils.StringUtil;
import wint.mvc.flow.FlowData;
import wint.mvc.module.LoadModuleService;
import wint.mvc.module.Module;
import wint.mvc.pipeline.PipelineContext;
import wint.mvc.template.Context;
import wint.mvc.template.ContextService;
import wint.mvc.view.ViewRender;
import wint.mvc.view.ViewRenderService;

/**
 * @author pister 2012-1-2 12:10:05
 */
public class PerformActionValve extends AbstractValve {

	private LoadModuleService loadModuleService ;
	
	private ContextService contextService;
	
	private ViewRenderService viewRenderService;
	
	private Configuration configuration;
	
	private String moduleActionName;
	
	private static final int MAX_REDIRECT_TIMES = 9;
	
	public void init() {
		super.init();
		loadModuleService = serviceContext.getService(LoadModuleService.class);
		contextService = serviceContext.getService(ContextService.class);
		viewRenderService = serviceContext.getService(ViewRenderService.class);
		
		configuration = serviceContext.getConfiguration();
		moduleActionName = configuration.getProperties().getString(Constants.PropertyKeys.APP_PACKAGE_WEB_ACTION, Constants.Defaults.APP_PACKAGE_WEB_ACTION);
	}

	public void invoke(PipelineContext pipelineContext, FlowData flowData) {
		perform(pipelineContext, flowData, 0);
		pipelineContext.invokeNext(flowData);
	}
	
	@SuppressWarnings("unchecked")
	private void perform(PipelineContext pipelineContext, FlowData flowData, int redirectTimes) {
		MagicList<Object> indexedParamters = (MagicList<Object>)flowData.getAttribute(Constants.FlowDataAttributeKeys.INDEXED_PARAMETERS);
		Module module = loadModuleService.loadModule(flowData.getTarget(), moduleActionName);
		Context context = contextService.createContext(flowData, indexedParamters);
		String target = module.execute(flowData, context, indexedParamters);
		
		if (flowData.isSendRedirected()) {
			if (log.isDebugEnabled()) {
				log.debug("the flow data is send redirect, break the pipeline.");
			}
			pipelineContext.breakPipeline();
		} else if (flowData.isRedirected()) {
			if (log.isDebugEnabled()) {
				log.debug("the flow data is redirect, redirected times: " + redirectTimes);
			}
			if (redirectTimes > MAX_REDIRECT_TIMES) {
				throw new FlowDataException("too many redirect times {"+ redirectTimes +"} !");
			}
			flowData.resetRedirected();
			++redirectTimes;
			perform(pipelineContext, flowData, redirectTimes);
		} else {
			String viewType = flowData.getViewType();
			if (StringUtil.isEmpty(viewType)) {
				ViewRender viewRender = viewRenderService.getDefaultViewRender();
				viewRender.render(context, flowData, target, module.getType());
			} else {
				ViewRender viewRender = viewRenderService.getViewRender(viewType);
				if (viewRender == null) {
					viewRender = viewRenderService.getDefaultViewRender();
				} 
				viewRender.render(context, flowData, target, module.getType());
			}
		}
	}
	

}
